/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mobiwebinc.compconn;

import com.mobiwebinc.compconn.announcer.Announcer;
import com.mobiwebinc.compconn.factory.AnnouncerFactory;
import com.mobiwebinc.compconn.client.ClientHandler;
import com.mobiwebinc.compconn.client.ClientList;
import com.mobiwebinc.compconn.communication.ChannelCleaner;
import com.mobiwebinc.compconn.communication.IOHandler;
import com.mobiwebinc.compconn.communication.Listener;
import com.mobiwebinc.compconn.configuration.ServerConfiguration;
import com.mobiwebinc.compconn.factory.SysTrayFactory;
import com.mobiwebinc.compconn.gui.MainMenu;
import com.mobiwebinc.compconn.screen.ScreenPackager;
import com.mobiwebinc.compconn.systray.SysTray;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author suraj
 */
public class Main {

    Listener listener;
    Announcer announcer;
    SysTray tray;
    ClientList clientList;
    private static Main main;
    private boolean recovered = false;
    private boolean running = false;
    private ChannelCleaner cleaner;

    /**
     * @param args the command line arguments
     */
    Main() throws IOException {
        tray = SysTrayFactory.getInstance().getSysTray();
        init();
    }

    public void init() throws IOException {
        ServerConfiguration serverConfiguration = ServerConfiguration.getInstance();
        listener = new Listener(serverConfiguration.getPort());
        announcer = AnnouncerFactory.getInstance().getAnnouncer();
        announcer.setParamters("OS", serverConfiguration.getOSName());
        if (serverConfiguration.isVisible()) {
            announcer.registerService(serverConfiguration.getName(), serverConfiguration.getPort());
        }
        clientList = ClientList.getInstance();
        cleaner = new ChannelCleaner();
        cleaner.start();
    }

    public static Main getInstance() {
        return main;
    }

    public static void main(String[] args) throws IOException {
        try {
            main = new Main();
            main.process();
        } catch (IOException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null, "Unable to setup server, check the configuration");
        }
    }

    private void process() {
        started();
        while (true) {
            IOHandler io = listener.getClient();
            if (io == null) {
                stopped();
                waitForRestart();
                started();
            } else {
                ClientHandler handler = new ClientHandler(io);
                clientList.addClient(handler);
                handler.start();
            }
        }
    }

    private void started() {
        System.out.println("started");
        running = true;
        MainMenu.getMainMenu().setStatus(true);
    }

    private void stopped() {
        System.out.println("stopped");
        running = false;
        MainMenu.getMainMenu().setStatus(false);
    }

    private void waitForRestart() {
        synchronized (this) {
            try {
                if (!recovered) {
                    this.wait();
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        recovered = false;
    }

    private void recoverFromStop() {
        synchronized (this) {
            recovered = true;
            this.notify();
        }
    }

    public void stop() {
        if (!running) {
            return;
        }
        running = false;
        announcer.stop();
        listener.stop();
        cleaner.done();
        ScreenPackager.getInstance().stopIt();
        clientList.disconnectAll();
    }

    public void start() {
        if (running) {
            return;
        }
        running = true;
        try {
            init();
        } catch (IOException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null, "Unable to setup server, check the configuration");
        }
        recoverFromStop();
    }

    public void restart() {
        stop();
        start();
    }
}
